import 'dart:convert';
import 'dart:io';

import 'package:im_app/im/pojo/ImPojo.dart';
import 'package:im_app/im/util/ImRichTextUtil.dart';
import 'package:im_app/im/util/ImSingleton.dart';
import 'package:im_app/im/util/ImageUtil.dart';
import 'package:logger/logger.dart';

import '../socket/dto/business/Message.dart';
import '../socket/dto/business/PullData2.dart';
import 'FileUtil.dart';
import 'Md5Util.dart';

class MessageUtil {

  static final _logger = Logger(printer: PrettyPrinter(),);

  static Future<MessageObject> toMessageObject(ImMessage imMessage) async {
    MessageObject messageObject = MessageObject(imMessage.fromUserId, imMessage.content,
        MessageType.ofName(imMessage.messageType.name));
    messageObject.localSeq = imMessage.clientId;
    messageObject.bean = await MessageUtil.buildContent(imMessage);
    messageObject.groupCode = imMessage.groupCode;
    messageObject.toUserId = imMessage.toUserId;
    if (imMessage.refType != null) {
      messageObject.refMessageIds = imMessage.refMessageIds;
      messageObject.refType = MessageRefType.ofName(imMessage.refType!.name);
    }
    if (imMessage.messageType!.isFile()) {
      FileItem fileItem = messageObject.bean as FileItem;
      messageObject.content = jsonEncode(fileItem.toJson());
    }
    return messageObject;
  }

  static Future<Object> buildContent(ImMessage imMessage) async {
    if (imMessage.messageType == ImMessageType.Text || imMessage.messageType == ImMessageType.Html
        || imMessage.messageType == ImMessageType.RichText || imMessage.messageType == ImMessageType.Web
        || imMessage.messageType == ImMessageType.Url || imMessage.messageType == ImMessageType.Chat) {
      return imMessage.content;
    } else if (imMessage.messageType.isFile()) {
      MessageExt? messageExt = imMessage.messageExt;

      if (messageExt != null && messageExt.fileName != null) {
        return FileItem(fileName: messageExt.fileName,
          fileUrl: messageExt.fileUrl,
          md5: messageExt.md5,
          size: messageExt.size,
          originalName: messageExt.originalName,
          time: messageExt.time,
          imageWidth: messageExt.imageWidth,
          imageHeight: messageExt.imageHeight
        );
      } else {
        var filePath = await MessageUtil.getFilePath(imMessage);
        File file = File(filePath);
        var path = file.path;
        var filename = path.split("/").last;
        var md5 = fileSha512(path);
        var imageSize = await ImageUtil.getImageSize(filePath);

        return FileItem(fileName: filename,
            fileUrl: imMessage.content,
            md5: md5,
            size: file.lengthSync(),
            originalName: filename,
            time: 0,
            imageWidth: imageSize[0],
            imageHeight: imageSize[1]
        );
      }
    } else {
      throw Exception("不支持这种模式 ${imMessage.messageType}");
    }
  }

  static String buildLastedMessage(ImMessageType messageType, String content) {
    if (messageType.isFile()) {
      if (messageType == ImMessageType.Image) {
        return "[图片]";
      } else if (messageType == ImMessageType.File) {
        return "[文件]";
      } else if (messageType == ImMessageType.Audio) {
        return "[音频]";
      } else if (messageType == ImMessageType.Video) {
        return "[视频]";
      } else {
        _logger.e("ImMessageType不支持这种类型: ${ImMessageType}");
      }
    } else {
      var str = content.replaceAll("\n", "");
      var spans = ImRichTextUtil.splitEmojis(str);
      var selectSpans = ImRichTextUtil.getSelectSpan(spans, 0, 30);
      return ImRichTextUtil.emojisToString(selectSpans);
    }
    return content;
  }

  static Future<String> getFilePath(ImMessage message) async {
    if (!message.messageType.isFile()) {
      throw Exception("不是文件消息，不能调用此方法");
    }
    if (!message.content.startsWith("/")) {
      return message.content;
    }
    if (message.messageExt!.remote) {
      String rootDir = await FileUtil.getFileRoot();
      return rootDir + message.content;
    }
    var filePath = message.content;
    var file = File(filePath);
    if (file.existsSync()) {
      return filePath;
    } else {
      String rootDir = await FileUtil.getFileRoot();
      return rootDir + message.content;
    }
    return message.content;
  }

  static String getFilePath2(ImMessage message) {
    if (!message.messageType.isFile()) {
      throw Exception("不是文件消息，不能调用此方法");
    }
    if (message.messageExt == null) {
      message.initMessageExt();
    }
    if (message.messageExt?.remote??false) {
      String rootDir = ImSingleton.getInstance().rootDir;
      var path = rootDir + message.content;
      var file = File(path);
      if (file.existsSync()) {
        return path;
      }
    }
    if (message.messageExt == null) {
      var file = File(message.content);
      if (file.existsSync()) {
        return message.content;
      } else {
        String rootDir = ImSingleton.getInstance().rootDir;
        return rootDir + message.content;
      }
    } else {
      String rootDir = ImSingleton.getInstance().rootDir;
      String file = rootDir + message.content;
      var isExisted = FileUtil.fileExisted(file);
      if (isExisted) {
        return file;
      }
    }
    return message.content;
  }

  static String getFilePath4(String path) {
    var fileUrl = '';
    if (!path.startsWith("file:")) {
      String rootDir = ImSingleton.getInstance().rootDir;
      fileUrl = rootDir + path;
    } else {
      fileUrl = path;
    }
    return fileUrl;
  }

  static String getFilePath3(ImFile imFile) {
    if (imFile.isRelativePath??false) {
      String rootDir = ImSingleton.getInstance().rootDir;
      return rootDir + imFile.path;
    }
    var file = File(imFile.path);
    if (file.existsSync()) {
      return imFile.path;
    } else {
      String rootDir = ImSingleton.getInstance().rootDir;
      return rootDir + imFile.path;
    }
    return imFile.path;
  }
}